 /**Spring 2013 Group 13 Automatic Handshake Contact Information Exchanger**
  **This sketch is responsible for detecting a handshake and transferring **
  **contact information between the two devices. After data transfer it   **
  **will store the received contact info into the device's external memory**
  **when the user wants to read the contents of the memory they have to   **
  **upload the memory read code and once finished re-upload this code to  **
  **the device                                                            **/

#include <Wire.h>
#define extMemory 0x50

struct card {
byte name[30];
 byte company[30];
byte phone[30];
byte email[30];
};

card test = {"Name: William Hanley", "Company: Company X", "Phone: 312-208-6151", "E-mail: hanley7@illinois.edu"};     
card test1;                              //^device business card to be transferred

const int Master = 1;
const int cell = 1;

const int xpin = A2;                  // x-axis of the accelerometer 
const int ypin = A1;                  // y-axis
const int zpin = A0;                  // z-axis

const int lowmem = 2;

int sampleDelay = 100;   //number of milliseconds between readings 
int led = 13;
int xvalue, yvalue, zvalue;
int xold, zold, yold;
int downcount, upcount;
int downflag, swingcheck;
int delta, deltaz, deltay;
int tryx; 
int arm_extend, arm_swing;
int shake_flag, swing_count, shake_try;
int handshake;
int i,j,m;
int connect1 = 0;
int connect2 = 0;
int endc = 0;
int endcc = 0;
int killed = 0;
int sreceive = 0;
int mreceive = 0;

byte pointer;
int offset;

char tx, rx;
char ch, prevch;
char Mastertx, Masterrx;
 
int sizename = sizeof(test.name);                        //these size variables are so you can change the size of the business card
int sizecompany = sizeof(test.company);
int sizephone = sizeof(test.phone);
int sizeemail = sizeof(test.email); 

int sizetotal = sizename + sizecompany + sizephone + sizeemail;

void setup()
 {

  Serial.begin(9600);
  Wire.begin();
  delay(30);

  pinMode(xpin, INPUT);
  pinMode(ypin, INPUT);
  pinMode(zpin, INPUT); 
  pinMode(led, OUTPUT);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
  pinMode(10, OUTPUT);
  digitalWrite(led, LOW);  

  downcount = 0;
  upcount = 0;
  tryx = 0;
  downflag = 0;
  swingcheck = 0;
  arm_extend = 0;
  arm_swing = 0;
  swing_count = 0;
  shake_flag = 0;
  yvalue = 0;
  shake_try = 0;
  handshake = 0;

  Serial.begin(9600);
}

void loop()
{
  if (digitalRead(8) == HIGH)        //read the inputs from the user switches
    tx = '1';
  else
    tx = '0';
  if (digitalRead(9) == HIGH)
    rx = '1';
  else
    rx = '0';     

  xvalue = analogRead(xpin);         //read accelereation values on each axis
  delay(1); 

  yold = yvalue; 
  yvalue = analogRead(ypin);  
  delay(1);     
 
  zvalue = analogRead(zpin);



  if ((xvalue > 595) && (xvalue < 625)) {   //check if the users arm is by their side for 2 cycles
    downcount++;                             
    if (downcount >= 2) {
      downflag = 1;
      xold = xvalue;                        //if it is then set the xvalue to xold
    }
  }

  else {                                   //if it isnt then check if the difference between the current  
    downcount = 0;                         //xvalue and the previous one is greater than 40
    tryx++;
    if (tryx >= 18) {
      downflag = 0;
      tryx= 0;
    } 
 
    else {
      delta = xold - xvalue;
      if ((delta >= 35) && (downflag == 1)) {    //if it is greater than 40 set the arm extend flag used
       arm_extend = 1;                           //later
       downflag = 0;
      }
      else {                                     //if not try again until the tryx timer resets
       arm_extend = 0; 
       tryx++;
      }  
    }
  }

  if (swingcheck == 1) {                         //this part of the code checks if the user swings their 
     deltaz = zold - zvalue;                     //arm perpindicular to their body
     deltaz = abs(deltaz);
     if ((deltaz >= 14) && (((xvalue < 540) && (xvalue > 505)) && ((yvalue < 625) && (yvalue > 600)))) {
       arm_swing = 1;                           //if the change in "z" acceleration is greater than 14 and 
       swingcheck = 0;                          //x and y are int he right position, set the arm_swing flag 
       upcount = 0;                             //used later
     }
     else arm_swing = 0;
  }   

  if (((xvalue < 540) && (xvalue > 505)) && ((yvalue < 630) && (yvalue > 600))) {
    upcount++;                                 //this part also checks for a swing by counting the cycles
    if (upcount >= 2) {                        //the arm is perpendicular to the body and setting the check 
      swingcheck = 1;                          //for an arm swing flag
      zold = zvalue;
    }
    else {
      swingcheck = 0;                          
    }  
  }
  else {
    upcount = 0;
  }

  if ((arm_swing == 1) || (arm_extend == 1))  {   //if there is either an arm_swing or arm_extend then  
                                                  //we set the flag to check for hand shake   
    shake_flag = 1;                               
    arm_swing = 0;
    arm_extend = 0;
  }  

  if (shake_flag != 0) {                          //check for 15 cycles
    shake_flag++;
    if (shake_flag >= 15) {
      shake_flag = 0;
    }
  }  

  if (shake_flag != 0) {                          //if the shake flag is set check for a handshake
    if (((zvalue < 545) && (zvalue > 490)) && ((xvalue < 590) && (xvalue > 435))) {
      deltay = yold - yvalue;
      deltay = abs(deltay);
      if (deltay > 37) {
        swing_count++;
      }  
      else {
        shake_try++;
        if (shake_try >= 5) {
         swing_count = 0;
         shake_try = 0;
        }
      }
      if (swing_count == 2) {                    //if there are two oscillations of the yvalue 
                                                 //greater than 37 then a handshake has occured
        handshake = 1;
        swing_count = 0;
        shake_try = 0; 
        shake_flag = 0;
      }
    }
    else {
      swing_count = 0;
      shake_try = 0;
    }  
 } 

 if (handshake == 1) {
   handshake = 0;
   digitalWrite(led, HIGH);          //light led due to a handshake
   delay(350);
   digitalWrite(led, LOW); 
   delay(25);

  if (cell == 1) {                  //send business card to a cell phone  
   Serial.println();                //if desired
   Serial.println();
   Serial.println("Name: William Hanley");
   Serial.println("Company: Company X");
   Serial.println("Phone: 312-208-6151"); 
   Serial.println("E-mail: hanley7@illinois.edu");
   Serial.println();
   Serial.println();
  }

  if ((tx != '0') || (rx != '0')){  
   if (Master == 1) {                  //if you are the Master, initiate connection with slave
     Serial.print("$$$");
     delay(1000);
     
  /* Serial.println("IN,2,001F00");            //inquiry scan for other device
     delay(9500);
     Serial.println("SR,I");
     delay(100);*/

     Serial.println("C,000666494895");      //used hardcoded connect for testing because it is faster 
     delay(5000); 

     Serial.println("---");
     delay(1000);
     while (Serial.available())
     Serial.read();
     Serial.print(".."); 
     Serial.print(tx);                //these bits will come from User Switches
     Serial.print(rx);                //add if statement with condition on Mastertx for sending data
     delay(50);
 
     if (tx == '1') {
         for (i = 0; i < sizename; i++) {         
           Serial.print((char)test.name[i]);
           delay(5);
         }

         for (i = 0; i < sizecompany; i++) {
           Serial.print((char)test.company[i]);
           delay(5);
         }

         for (i = 0; i < sizephone; i++) { 
           Serial.print((char)test.phone[i]);
           delay(5);
         }
         for (i = 0; i < sizeemail; i++) {
           Serial.print((char)test.email[i]);
            delay(5);
         }     
     }                                     
   }

   else{                              //If you are the slave do nothing (for now) 
   }
  } 
 }

    if (Master == 0) {          
     if (Serial.available() > 0){
       prevch = ch;                                //checking for the start word
       ch = (char)Serial.read();
       if ((ch == '.') && (prevch == '.'))
         connect1 = 1;
       else  
         connect1 = 0;  
 
       if (connect1 == 1){           //read in Mastertx and rx bits if start word is detected
         delay(50);
         Mastertx = (char)Serial.read();
         Masterrx = (char)Serial.read();          
         connect1 = 0;
       } 

      if ((Mastertx == '0') && (tx == '0')) {
       Serial.print("**"); 
       Mastertx = 's';
       Masterrx = '@';}

      if (Mastertx == '1') {                      //need to add Slave recieve switch reading 
        if (rx == '1') {
         for (i = 0; i < sizename; i++) {         //read in buisness card data from master device
            while (Serial.available() == 0);      //to card structure
            test1.name[i] = (byte)Serial.read();
         }

         for (i = 0; i < sizecompany; i++) { 
           while (Serial.available() == 0);
           test1.company[i] = (byte)Serial.read();
           delay(5);
         }

         for (i = 0; i < sizephone; i++) { 
           while (Serial.available() == 0);
           test1.phone[i] = (byte)Serial.read();
           delay(5);
         }

         for (i = 0; i < sizeemail; i++) { 
           while (Serial.available() == 0);
             test1.email[i] = (byte)Serial.read();
             delay(5);
         }
         Mastertx = '@'; 
         sreceive = 1;}
 
         if (Masterrx == '0') {     
         Serial.print("**");
         Masterrx = 's';}

         
         if ((Masterrx == '1') && (tx == '0')) { 
         Serial.print("**");
         Masterrx = 's';}           
           
         }
     }

                  
      if ((Masterrx == '1') && (tx == '1')) {                 
        if (Serial.available() == 0){             //Send buisness card data to master device
           Serial.print(">>"); 
         for (i = 0; i < sizename; i++) {         //read buisness card data from master device
            Serial.print((char)test.name[i]);
            delay(5);
         }

         for (i = 0; i < sizecompany; i++) {
           Serial.print((char)test.company[i]);
           delay(5);
         }

         for (i = 0; i < sizephone; i++) {
           Serial.print((char)test.phone[i]);
           delay(5);
         }

          for (i = 0; i < sizeemail; i++) {
           Serial.print((char)test.email[i]);
           delay(5);
         }        

         Masterrx = '@'; 
         Serial.print("<<");      
       }                
      }
     }

   if (Master == 1) {                              //if the device is the master listen for 
     if (Serial.available() > 0) {                 //the slave to send their data
         prevch = ch;
         ch = (char)Serial.read();
         delay(10);
       if ((ch == '>') && (prevch == '>')){
         connect2 = 1;
         }
       else if ((ch == '<') && (prevch == '<')){ 
         endc = 1;}
       else if ((ch == '*') && (prevch == '*')){  
         endcc = 1;       
       }
       else  {
         connect2 = 0; 
         endc = 0;
         endcc = 0;}

       if ((connect2 == 1) && (rx == '1')) {          
         for (i = 0; i < sizename; i++) {             //read buisness card data from master device
           while (Serial.available() == 0);
           test1.name[i] = (byte)Serial.read();
         }

         for (i = 0; i < sizecompany; i++) {
           while (Serial.available() == 0);
           test1.company[i] = (byte)Serial.read();
         }

         for (i = 0; i < sizephone; i++) { 
           while (Serial.available() == 0);
           test1.phone[i] = (byte)Serial.read();
         }

         for (i = 0; i < sizeemail; i++) {
           while (Serial.available() == 0);
           test1.email[i] = (byte)Serial.read();
        }

       connect2 = 0;
       mreceive = 1; 
     }
   }     
  }

  
  if (Master == 1){                      //if you are the Master kill the connection after 
    if ((rx == '1') && (endc == 1)) {    //after data transfer
      delay(1000);
      Serial.print("$$$");
      delay(1001);
      Serial.println("K,");
      endc = 0;
      killed = 1;
    } 

    if (((rx == '0') || (rx == '1')) && (endcc == 1)) {
      delay(1000);
      Serial.print("$$$");
      delay(1001);
      Serial.println("K,");
      endcc = 0;
      killed = 1;
    }       
  }

    if ((Master == 1) && (killed == 1) && (rx == '1') && (mreceive == 1)) {      
     pointer = memoryRead(0);                        //if you are the master and recieve data
     delay(5);                                       //after a handshake store it to the 
     if ((pointer + 1) > lowmem)                     //external memory
       digitalWrite(10, HIGH);
     else
       digitalWrite(10, LOW);  
     offset = ((pointer*sizetotal) + 1);
     for (i = offset; i < sizename + offset; i++) {
       memoryWrite(i, test1.name[i - offset]);
      delay(10);
     }

     offset = offset + sizename; 

     for (i = offset; i < sizecompany + offset; i++) { 
      memoryWrite(i, test1.company[i - offset]);
      delay(10);
     }

     offset = offset + sizecompany;

     for (i = offset; i < sizephone + offset; i++) { 
      memoryWrite(i, test1.phone[i - offset]);
      delay(10);
     }

     offset = offset + sizephone;

     for (i = offset; i < sizeemail + offset; i++) { 
      memoryWrite(i, test1.email[i - offset]);
      delay(10);

     }

     offset = offset + sizeemail;      

     pointer++;
     delay(5);
     memoryWrite(0, pointer);
     delay(10);

     killed = 0;
     mreceive = 0;
   } 

 
   if ((Master == 0) && (sreceive == 1)) {        //if you are the slave and recieve data after a 
     pointer = memoryRead(0);                     //handshake store it to the external memory
     delay(5);
     if (pointer+1 > lowmem)
       digitalWrite(10, HIGH);
     else
       digitalWrite(10, LOW);      
     offset = ((pointer*sizetotal) + 1);

     for (i = offset; i < sizename + offset; i++) {
      memoryWrite(i, test1.name[i - offset]);
      delay(10);
     }

     offset = offset + sizename; 

     for (i = offset; i < sizecompany + offset; i++) {
      memoryWrite(i, test1.company[i - offset]);
      delay(10);
     }

     offset = offset + sizecompany;

     for (i = offset; i < sizephone + offset; i++) {
      memoryWrite(i, test1.phone[i - offset]);
      delay(10);
     }

     offset = offset + sizephone;

     for (i = offset; i < sizeemail + offset; i++) {
      memoryWrite(i, test1.email[i - offset]);
      delay(10);
     }

     offset = offset + sizeemail;      

     pointer++;
     delay(5);
     memoryWrite(0, pointer);
      delay(10);
     sreceive = 0;
   }   

   delay(sampleDelay);                          //delay before next reading
}



void memoryWrite(int address, byte data) {        //custom function to write to external memory 
  byte highAddress;
  byte lowAddress;

  highAddress = highByte(address);
  lowAddress = lowByte(address);

  Wire.beginTransmission(extMemory);
   Wire.write(highAddress);
  Wire.write(lowAddress);
  Wire.write(data);
  Wire.endTransmission();

}

byte memoryRead(int address) {                    //custom function to read from external memory 
  byte highAddress;
  byte lowAddress;

  highAddress = highByte(address);
  lowAddress = lowByte(address);  
  
  Wire.beginTransmission(extMemory);
  Wire.write(highAddress);
  Wire.write(lowAddress);
  Wire.endTransmission();
  
  Wire.requestFrom(extMemory, 1);

  while(!Wire.available()) {
   }

  return Wire.read();
} 